﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Serialization;
using BLToolkit.EditableObjects;
using BLToolkit.Reflection;
using System.IO;
using BLToolkit.Mapping;
using BLToolkit.TypeBuilder;

namespace LED_Editor.Config {
	[XmlType(AnonymousType = true)]
	public abstract class ConfigurationInstance : EditableObject {
	}

	public class Configuration<L>
			where L : ConfigurationInstance {

		//private static G _globalConfig;
		private static L _localConfig;

		public static string LocalConfigName = "local.config";

		//public static G Global
		//{
		//    get
		//    {
		//        if (_globalConfig == null)
		//            LoadGlobalGonfig();

		//        return _globalConfig;
		//    }
		//}

		public static L Local {
			get {
				if (_localConfig == null)
					LoadLocalConfig();

				return _localConfig;
			}
		}

		private static void LoadLocalConfig() {
			_localConfig = TypeAccessor<L>.CreateInstance();

			if (File.Exists(LocalConfigName)) {
				using (FileStream fs = new FileStream(LocalConfigName, FileMode.Open)) {
					XmlSerializer xs = new XmlSerializer(TypeAccessor<L>.Type);
					L loadedInstance = (L)xs.Deserialize(fs);

					if (loadedInstance != null)
						Map.ObjectToObject(loadedInstance, _localConfig);
				}

			}
		}

		//        public abstract class GlobalConfig
		//        {
		//            [MapIgnore(false)]
		//            public abstract SqlXml Config { get; set; }
		//        }

		//        public abstract class GlobalConfigAccessor : DataAccessor<GlobalConfig, GlobalConfigAccessor>
		//        {
		//            [SqlQuery(
		//                @"IF NOT EXISTS (SELECT name FROM sysobjects WHERE name = 'GlobalConfig') 
		//				BEGIN
		//					CREATE TABLE [GlobalConfig]
		//					(
		//						[Config] [XML] NOT NULL
		//					)
		//				END
		//
		//				SELECT TOP 1 [Config] FROM [GlobalConfig]")]
		//            public abstract GlobalConfig Select();

		//            [SqlQuery(
		//                @"IF NOT EXISTS (SELECT name FROM sysobjects WHERE name = 'GlobalConfig') 
		//				BEGIN
		//					CREATE TABLE [GlobalConfig]
		//					(
		//						[Config] [XML] NOT NULL
		//					)
		//				END
		//
		//				DELETE FROM [GlobalConfig]
		//				INSERT INTO [GlobalConfig] ([Config]) VALUES (@Config)")]
		//            public abstract int Update(GlobalConfig config);

		//            [SqlQuery(
		//                @"IF NOT EXISTS (SELECT name FROM sysobjects WHERE name = 'GlobalConfig') 
		//				BEGIN
		//					CREATE TABLE [GlobalConfig]
		//					(
		//						[Config] [XML] NOT NULL
		//					)
		//				END
		//
		//				DELETE FROM [GlobalConfig]")]
		//            public abstract void ToDefaults();
		//        }

		//        private static void LoadGlobalGonfig()
		//        {
		//            _globalConfig = TypeAccessor<G>.CreateInstance();

		//            GlobalConfig globalConfig = GlobalConfigAccessor.CreateInstance().Select();
		//            if (globalConfig != null)
		//            {
		//                XmlSerializer xs = new XmlSerializer(TypeAccessor<G>.Type);
		//                //XmlReader r = XmlReader.Create(globalConfig.Config.InnerXml);

		//                G loadededInstance = (G)xs.Deserialize(globalConfig.Config.CreateReader());

		//                if (loadededInstance != null)
		//                    Map.ObjectToObject(loadededInstance, _globalConfig);
		//            }
		//        }

		public static void Save() {
			SaveLocal();
			//SaveGlobal();
		}

		//public static void SaveGlobal()
		//{
		//    using (MemoryStream s = new MemoryStream())
		//    {
		//        XmlSerializer xs = new XmlSerializer(TypeAccessor<G>.Type);
		//        GlobalConfig g = TypeAccessor<GlobalConfig>.CreateInstance();

		//        xs.Serialize(s, Global);
		//        s.Position = 0;
		//        SqlXml sqlXml = new SqlXml(s);
		//        s.Position = 0;
		//        g.Config = sqlXml; //  XmlReader.Create(s);

		//        using (DbManager db = new DbManager())
		//        {
		//            IDbDataParameter[] pars = db.CreateParameters(g);
		//        }

		//        GlobalConfigAccessor.CreateInstance().Update(g);

		//        Global.AcceptChanges();
		//    }
		//}

		public static void SaveLocal() {
			#region Local

			using (FileStream fs = new FileStream(LocalConfigName, FileMode.Create)) {
				XmlSerializer xs = new XmlSerializer(TypeAccessor<L>.Type);
				xs.Serialize(fs, Local);
			}

			Local.AcceptChanges();

			#endregion
		}

		public static void Reset() {
			ResetLocal();
			//ResetGlobal();
		}

		public static void ResetLocal() {
			_localConfig = null;
		}

		//public static void ResetGlobal()
		//{
		//    _globalConfig = null;
		//}

		public static void ToDefaults() {
			ToDefaultsLocal();
			//ToDefaultsGlobal();
		}

		public static void ToDefaultsLocal() {
			if (File.Exists(LocalConfigName))
				File.Delete(LocalConfigName);

			ResetLocal();
		}

		//public static void ToDefaultsGlobal()
		//{
		//    GlobalConfigAccessor.CreateInstance().ToDefaults();

		//    ResetGlobal();
		//}

	}

	public class ConfigurationBase<L> : Configuration<L>
			where L : ConfigurationInstance {
	}

	public class LedEditorConfig : ConfigurationBase<LocalConfig> { }

	[XmlType(AnonymousType = true)]
	public abstract class LocalConfig : ConfigurationInstance {
		[Parameter(115200)]
		public abstract int BaudRate { get; set; }

		[Parameter("COM5")]
		public abstract string PortName { get; set; }
	}
}
